@rem __________________________________________________________________________
@rem
@rem    Abstract:
@rem        Expands environment variables and includes files.
@rem
@rem    To set an environment variable FOO to 1: !set FOO=1
@rem    To use an environment variable FOO :  version=v%FOO%
@rem    To include another file:  !include "%mypath%\myfile.xml"
@rem    Quotes are mandatory around filename in a !include
@rem    included file may include more files or define new variables
@rem
@rem    Author:
@rem        kjordan, mohkhan, ddoub
@rem __________________________________________________________________________

@if "%_echo%"=="" echo off

setlocal
perl.exe -w -x "%~f0" %*
endlocal
exit /b

#!perl

my $file;

my $optWarn = 1;
my $optUndefined = 1;

if (@ARGV == 0) {
    usage()
}

foreach $file (@ARGV) {

    if (lc("$file") =~ /^[\/-]+no-warn/) {
        $optWarn = 0;
    } elsif (lc("$file") =~ /^[\/-]+no-undefined/) {
        $optUndefined = 0;
    } elsif ("$file" =~ /^[\/-]+\?/) {
        usage();
    } elsif ("$file" =~ /^[\/-]+.*/) {
        print STDERR "EXPANDENV : fatal error ENV1002: Invalid option $file!\n";
        exit(0);
    } else {
        process($file, 'fh00');
    }
}

sub usage {
    print "\n";
    print " [CoReXT] ExpandEnv.cmd (kjordan/mohkhan/ddoub) \n";
    print "\n";
    print " syntax:\n";
    print "   expandenv.cmd [options] file1 [file2 ...]\n";
    print "\n";
    print " Expands environment variables in one or more input file(s).\n";
    print "\n";
    print " options:\n";
    print "   --?            : this help screen\n";
    print "   --no-warn      : disable warnings\n";
    print "   --no-undefined : do not keep undefined variables\n";
    exit(0);
}

sub process {
    my($filename, $input) = @_;
    $input++;               # this is a string increment
    unless (open($input, $filename)) {
        print STDERR "EXPANDENV : fatal error ENV1001: Can't open $filename: $!\n";
        exit(0);
    }

    local $_;
    while (<$input>) { 
        if (/^\s*!include "(.*)"/) {
            process(expand($1), $input);
            next;
        }
        elsif(/^\s*!set ([^ =]*) *=([^\n]*)/) {
            $ENV{uc $1} = $2;
        }
        else {
            print expand($_);       
        }

    }
}

sub expand {
  my ($line) = @_;
  my $scanpos;
  my $startvar;
  my $endvar;
  my $variable_value;
  my $variable_name;
        
    # find all %foo% elements
    $scanpos = 0;
    while (($startvar = index($line, "%", $scanpos)) >= 0)
    {
       $endvar = index($line, "%", $startvar+1);
       if ($endvar <= $startvar)
       {
           # only one percent: leave line as is
           last;
       }
       elsif ($endvar == ($startvar + 1))
       {
            # %%: change to %, and restart scan after %
            $line = substr($line, 0, $startvar+1) . substr($line, $startvar+2);
            $scanpos = $startvar + 1;
       }
       else
       {
            # %var%: see if variable is defined
            $variable_name = substr($line, $startvar+1, $endvar-$startvar-1);
            $variable_value = $ENV{uc($variable_name)};

            # set the variable if not optUndefined
            if ((! defined $variable_value) && ($optUndefined == 0)) {
                $variable_value = "";
            }

            if (defined $variable_value) {
                # variable is defined: replace it and rescan   
                $line = substr($line, 0, $startvar) . $variable_value . substr($line, $endvar+1);
                $scanpos = $startvar;
            } else {
                # variable is not defined: leave it as %var% and continue scanning after that
                if ($optWarn) {
                    print STDERR "EXPANDENV : warning ENV0001: undefined variable $variable_name\n";
                }
                $scanpos = $endvar + 1;
            }
       }
    }
    return $line;
}
